#include <string.h>
#include <stdlib.h>
#include "Comutil.h"


CPtrList::CPtrList()
{
	m_pHead = NULL;
	m_pTail = NULL;
	
	m_nCount = 0;
}

CPtrList::~CPtrList()
{
	//printf("CPtrList destroyed\n");
	//if ( m_pHead!=NULL ) printf("Memory Leak Detected\n");

	LPNODE pNode = m_pHead;
	while ( pNode!=NULL )
	{
		m_pHead = pNode->m_pNext;
		free( pNode );
		pNode = m_pHead;
	}
	m_pHead = m_pTail = NULL;
	m_nCount = 0;
}

int CPtrList::Count() const
{
	return(m_nCount);
}

int CPtrList::Add(void *pItem)
{
	LPNODE pNode = (LPNODE) malloc(sizeof(NODE));
	
	pNode->m_pNext = NULL;
	pNode->m_pPrev = m_pTail;
	pNode->m_pItem = pItem;

	if ( m_pTail!=NULL ) m_pTail->m_pNext = pNode;
	if ( m_pHead==NULL ) m_pHead = pNode;

	m_pTail = pNode;
	m_nCount ++;

	return m_nCount;
}

LPVOID CPtrList::DeleteNode(LPNODE &pNode)
{
	LPVOID item;
	LPNODE PrevNode, NextNode;

	if ( pNode==NULL ) return(NULL);

	PrevNode = pNode->m_pPrev;
	NextNode = pNode->m_pNext;
	if ( PrevNode!=NULL )
	{
		PrevNode->m_pNext = NextNode;
	}
	else
	{//PrevNode==NULL mean that the deleted node is the first node, so modify the head value
		m_pHead = NextNode;
	}
	if ( NextNode!=NULL )
	{
		NextNode->m_pPrev = PrevNode;
	}
	else
	{//NextNode==NULL mean that the deleted node is the last node, so modify the tail value
		m_pTail = PrevNode;
	}
	m_nCount --;

	item = pNode->m_pItem;
	free(pNode);
	return item;
}

int CPtrList::Delete( LPVOID pItem)
{
	LPNODE pNode, curNode;
	if ( (pItem==NULL)||(this==NULL) ) return -1;

        pNode = m_pHead;
        while ( pNode!=NULL )
	{
		curNode = pNode->m_pNext;
		if ( pNode->m_pItem == pItem )
		{
			DeleteNode(pNode);
		}
		pNode = curNode;
	}
        return 0;
}

int CPtrList::IndexOf( LPVOID pItem)
{
	int i;
	LPNODE pNode;
	if ( (pItem==NULL)||(this==NULL) ) return -1;

	pNode = m_pHead;
	for (i=0, pNode=m_pHead;pNode!=NULL;i++, pNode=pNode->m_pNext )
	{
		if ( pNode->m_pItem == pItem ) return i;
	}
	return -1;
}

LPVOID CPtrList::Delete(int nIndex)
{
	int i;
	LPNODE pNode;
	if ( (this==NULL)||(m_pHead==NULL) ) return (NULL);
	if ( (nIndex<0)||(nIndex>=m_nCount) ) return(NULL);
	
	pNode = m_pHead;
	for ( i=0;(i<nIndex)&&(pNode!=NULL);i++ ) pNode = pNode->m_pNext;
	
	if ( pNode!=NULL ) return DeleteNode(pNode);
	else return(NULL);
}

LPVOID CPtrList::Item(int nIndex)
{
	int i;
	LPNODE pNode;
	if ( (this==NULL)||(m_pHead==NULL) ) return NULL;
	if ( (nIndex<0)||(nIndex>=m_nCount) ) return NULL;

        pNode = m_pHead;
	for ( i=0;(i<nIndex)&&(pNode!=NULL);i++ ) pNode = pNode->m_pNext;

	if ( pNode!=NULL ) return pNode->m_pItem;
	else return(NULL);
}

LPNODE CPtrList::GetHead()
{
	m_pIterator = m_pHead;
	return m_pHead;
}

LPNODE CPtrList::GetTail()
{
	m_pIterator = m_pTail;
	return m_pTail;
}

LPVOID CPtrList::getHead()
{
	GetHead();
	return getNext();
}

LPVOID CPtrList::getTail()
{
	GetTail();
	return getPrev();
}

LPVOID CPtrList::getNext()
{
	LPNODE p;
	if ( m_pIterator!=NULL )
	{
		p = m_pIterator;
		m_pIterator = p->m_pNext;
		return (p->m_pItem);
	}
	return (NULL);
}

LPVOID CPtrList::GetNext(LPNODE &pNode)
{
	LPNODE p;
	if ( pNode!=NULL )
	{
		p = pNode;
		pNode = p->m_pNext;
		return (p->m_pItem);
	}
	return(NULL);
}

LPVOID CPtrList::getPrev()
{
	LPNODE p;
	if ( m_pIterator!=NULL )
	{
		p = m_pIterator;
		m_pIterator = p->m_pPrev;
		return (p->m_pItem);
	}
	return (NULL);
}

LPVOID CPtrList::GetPrev(LPNODE &pNode)
{
	LPNODE p;
	p = pNode;
	if ( pNode!=NULL )
	{
		p = pNode;
		pNode = p->m_pPrev;
		return(p->m_pItem);
	}
	return(NULL);
}

CString::CString()
{
	m_ptr = NULL;
	__Copy( NULL );
}

CString::CString(char *str)
{
	m_ptr = NULL;
	__Copy( str );
}

CString::CString(CString & s)
{
	m_ptr = NULL;
	__Copy( s.m_ptr );
}

CString::~CString()
{
	Release();
}

char * CString::GetBuffer(int nMinBufLength)
{
	Release();
	m_ptr = (char*)malloc(nMinBufLength+20);

	if ( m_ptr!=NULL )
	{
		*m_ptr = 0;
		m_actsize = 0;
		m_maxsize = nMinBufLength + 20;
		return m_ptr;
	}
	return NULL;
}

void CString::Release()
{
	if ( m_ptr!=NULL )
	{
		free( m_ptr );
		m_ptr = NULL;
	}

	m_sparesize = 20;
	m_maxsize = 0;
	m_actsize = 0;
}

int CString::__Compare(char *str)
{
	if ( (m_ptr!=NULL)&&(str!=NULL) )
	{
		if ( strlen(m_ptr)==strlen(str) )
		{
			return ( strcmp(m_ptr,str)==0 );
		}
	}
	return 0;
}

void CString::__Copy(char *str)
{
	Release();
	if ( str==NULL ) return;

	int nsize = strlen(str);
	m_ptr = (char *)malloc(nsize + m_sparesize);
	if ( m_ptr!=NULL )
	{
		m_actsize = nsize;
		m_maxsize = m_actsize + m_sparesize;
		strcpy(m_ptr, str);
	}
}

void CString::__Plus(char *str)
{
	if ( str==NULL ) return;

	int nsize = strlen(str); 
	if ( m_ptr==NULL )
	{
		__Copy( str );
	}
	else if ( m_maxsize-m_actsize>nsize )
	{
		strcat( m_ptr, str );
		m_actsize += nsize;
	}
	else
	{
		if ( m_sparesize<200 ) m_sparesize += 20;
		nsize += m_actsize;
		char *p = (char *)malloc(nsize+m_sparesize);
		if ( p!=NULL )
		{
			strcpy(p, m_ptr);
			strcat(p, str);
			free( m_ptr );
			m_actsize = nsize;
			m_maxsize = m_actsize + m_sparesize;
			m_ptr = p;
		}
	}
}

char & CString::operator[](int nIndex)
{
	if ( (m_ptr==NULL)||(nIndex<0)||(nIndex>=m_actsize) ) return m_refch;
	return m_ptr[nIndex];
}

CString CString::operator+ (char *str)
{
	CString p( m_ptr );
	p.__Plus( str );
	return CString(p.m_ptr);
}

CString CString::operator+ (CString &s)
{
	CString p( m_ptr );
	p.__Plus( s.m_ptr );
	return CString(p.m_ptr);
}

int CString::IgnoreCaseCompare(char *str)
{
	CString p1(str);
	CString p2(m_ptr);

	p1.MakeLower();
	p2.MakeLower();
	return p1.__Compare(p2);
}

void CString::MakeLower()
{
	char *ch;
	if ( m_ptr!=NULL )
	{
		for (ch=m_ptr;(*ch)!=0;ch++)
		{
			if ( (*ch>='A')&&(*ch<='Z') ) *ch += 32;
		}
	}
}

void CString::MakeUpper()
{
	char *ch;
	if ( m_ptr!=NULL )
	{
		for (ch=m_ptr;(*ch)!=0;ch++)
		{
			if ( (*ch>='a')&&(*ch<='z') ) *ch -= 32;
		}
	}
}

void CString::MakeReverse()
{
	char *ch1, *ch2, ch;
	if ( m_ptr!=NULL )
	{
		ch1 = m_ptr;
		ch2 = m_ptr + m_actsize - 1;
		for (; ch1<ch2; ch1++, ch2--)
		{
			ch = *ch1;
			*ch1 = *ch2;
			*ch2 = ch;
		}
	}
}

void CString::TrimLeft()
{
	char *ch, *ch1;
	if ( m_ptr!=NULL )
	{
		for (ch=m_ptr; (*ch==' ');ch++) *ch = 0;
		ch1 = m_ptr;
		m_actsize = 0;
		for (; (*ch!=0); m_actsize++, ch1++, ch++) *ch1 = *ch;
		*ch1 = 0;
	}
}

void CString::TrimRight()
{
	char *ch;
	if ( m_ptr!=NULL )
	{
		for (ch=m_ptr+m_actsize-1; (*ch==' ')&&(m_actsize>0); m_actsize--, ch--)
		{
			*ch = 0;
		}
	}
}

void CString::AllTrim()
{
	TrimRight();
	TrimLeft();
}

int	CString::Find(char ch) const               // like "C" strchr
{
	if ( m_ptr==NULL ) return -1;
	char *p;
	int i;

	for (i=0, p=m_ptr; (*p!=0)&&(*p!=ch); p++) i++;
	if ( *p==0 ) return -1;
	else return i;
}

int CString::ReverseFind(char ch) const
{
	if ( m_ptr==NULL ) return -1;
	char *p;
	int i;

	for (i=m_actsize-1, p=m_ptr+i; (i>=0)&&(*p!=ch); p--) i--;
	return i;
}

int CString::Find(char *str) const
{
	return -1;
}

void CString::__Format(char *format, va_list va)
{
	char *p = (char*)malloc( strlen(format)+2048 );
	if ( p!=NULL )
	{
		vsprintf(p, format, va);
		__Copy( p );
		free( p );
	}
}

void CString::Format(char *format, ...)
{
	va_list va;
	va_start(va, format);
	__Format( format, va );
	va_end(va);
}

void CString::Append(char *format, ...)
{
	CString p;
	va_list va;
	va_start(va, format);
	p.__Format(format, va);
	va_end(va);
	__Plus( p.m_ptr );
}

CString CString::Left( int l)
{
	if ( (m_ptr==NULL)||(l<0) ) return CString( );

	CString p( m_ptr );
	if ( (l<m_actsize) ) p.m_ptr[l] = 0;
	return CString( p.m_ptr );
}

CString CString::Right( int l)
{
	if ( (m_ptr==NULL)||(l<0) ) return CString( );
	if ( (l>=m_actsize) ) l = m_actsize;
	return CString( m_ptr+m_actsize-l );
}

CString CString::Mid( int s, int l)
{
	if ( m_ptr==NULL ) return CString( );

	if ( s<0 ) s = 0;
	if ( (s>=m_actsize) ) return CString( );

	CString p( m_ptr+s );
	if ( l<p.m_actsize ) p.m_ptr[l] = 0;
	return CString(p.m_ptr);
}

//////////////////////////////////////////////////////////
// implement of class CStringList
//////////////////////////////////////////////////////////
CStringList::CStringList() : CPtrList()
{
}

CStringList::~CStringList()
{
	//printf("StringList destroyed\n");
	Clear();
}

int CStringList::Add( LPVOID pItem )
{
	char *p1, *p2;
 	p1 = (char *) pItem;
	if (p1[0]==0 ) return m_nCount;

	p2 = (char *) malloc( strlen(p1)+5 );

	if ( NULL!=p2 )
	{
		strcpy(p2, p1);
		CPtrList::Add( (LPVOID)p2 );
	}
	return m_nCount;
}

int CStringList::IndexOf( LPVOID pItem)
{
	int i;
	LPNODE pNode;
	char *p1, *p2 = (char*)pItem;
	if ( (pItem==NULL)||(this==NULL) ) return -1;

	pNode = m_pHead;
	for (i=0, pNode=m_pHead;pNode!=NULL;i++, pNode=pNode->m_pNext )
	{
		p1 = (char *)pNode->m_pItem;
		if ( strcmp(p1, p2)==0 ) return i;
	}
	return -1;
}

char * CStringList::Strings(int wIndex)
{
	LPVOID pItem;
	pItem = Item( wIndex );

	return ( (char*) pItem );
}

void CStringList::Clear()
{
	char *pItem;
	while ( m_nCount>0 )
	{
		pItem = (char*) RemoveHead();
		free( pItem );
	}
	m_pHead = m_pTail = NULL;
	m_nCount = 0;
}

void CStringList::Display()
{
	/*
	int i;
	printf("m_nCount=%d\n", m_nCount);
	for (i=0;i<m_nCount;i++)
	{
		printf("Display: %s\n", Strings(i));
	}
	*/
}


void ReadFileStr(FILE *FS, char *buf)
{
	unsigned char c = 0;
	fread(&c, 1, 1, FS);
	fread(buf,  1, c, FS);
	buf[c] = 0;
}

char *alltrim(char *src)
{
 	int i, j, nSize;
	for (nSize=strlen(src)-1;nSize>=0;nSize--) if (src[nSize]!=' ') break;
	nSize ++;
	for (i=0;i<nSize;i++) if ( (src[i]!=' ')&&(src[i]!=9) ) break;
	for (j=0;i<nSize;i++) src[j++] = src[i];
	src[j] = 0;
	return src;
}

int	MyStrToInt(const char *s)
{
	return atoi(s);
}

double	MyStrToFloat(const char *s)
{
	return atof(s);
}

int	myatoi(char *val)
{
	int ret;
	if ( (val[0]=='0')&&(strlen(val)>=3) )
	{
		ret = 0;
		if ( (val[1]=='x')||(val[1]=='X') )
		{
			for ( unsigned long i=2;i<strlen(val);i++)
			{
				int j = getHexValue( val[i] );
				if ( j<0 ) break;
				ret = (ret<<4) + j;
			}
			return ret;
		}
	}
	return atoi(val);
}

int BCDToInt(uchar *KeyBuf, int ctrl)
{
	if ( ctrl==2 )
	{
		int id = ((KeyBuf[0]>>4)&0xF) * 10 + (KeyBuf[0]&0xF);
		id = ((KeyBuf[1]>>4)&0xF) * 10 + (KeyBuf[1]&0xF) + id*100;
		return id;
	}
	else if ( ctrl==1 )
	{
		int id = ((KeyBuf[0]>>4)&0xF) * 10 + (KeyBuf[0]&0xF);
		return id;
	}
	else
	{
		return 1;
	}
	return 0;
}

/*
 *return 0 : ok ;  1 : error
 *ctrl	 1 : 1 bytes; 2: 2 bytes
 */
int IntToBCD(unsigned char * tempchar,int n , int ctrl)
{
	if ( ctrl==4 )
	{
		IntToBCD( tempchar, (n/10000)%10000, 2 );
		IntToBCD( tempchar+2, n%10000, 2);
		return 0;
	}
	else if (ctrl==2)
	{
		unsigned char c1,c2,c3,c4;
		c1 = (n % 10000) / 1000 ; 
		c2 = (n % 1000) / 100 ;
		c3 = (n % 100) / 10 ;
		c4 = n % 10 ; 

		tempchar[0] = BCD(c1,c2);
		tempchar[1] = BCD(c3,c4);
		if (n >= 10000) return 1;
	}
	else
	{
		unsigned char c1 , c2;
		c1 = (n % 100) / 10;
		c2 = n % 10 ;
		tempchar[0] = BCD(c1,c2);
		if (n >= 100) return 1;
	}
	return 0;
}

char ParseStr(const char *Buf, int &st, int dstlen, char *Dest)
{
	int j, len;
	len = strlen(Buf);

	while ( (st<=len)&&( (32==Buf[st])||(8==Buf[st])||(10==Buf[st])||(13==Buf[st])) ) st = st+1;

	j = 0;
	while ( (st<=len)&&(j<dstlen)&&(32!=Buf[st])&&(8!=Buf[st])&&(10!=Buf[st])&&(13!=Buf[st]) ) 
	{
		Dest[j] = Buf[st];
		st = st+1;
		j = j+1;
	}
	Dest[j] = 0;
	return 0;
}

void substr(char * src, char * dst, int b, int l)
{

	int i, ll = strlen(src);
	dst[0] = 0;
	if ( b>=ll ) return;
	
	if(ll>(b+l))
	{
		ll=b+l;
	}
	
	for (i=b;i<ll;i++) dst[i-b] = src[i];
	dst[ll-b] = 0;
}

int getHexValue(char ch)
{
	if ( (ch>='0')&&(ch<='9') ) return (ch-'0');
	if ( (ch>='A')&&(ch<='F') ) return (ch-'A'+10);
	if ( (ch>='a')&&(ch<='f') ) return (ch-'a'+10);
	return -1;
}

void decodeHttpCode( char *httpcode )
{
	int i, j, wSize;
	wSize = strlen(httpcode);
	char ch;
	j = 0;
	i = 0;
	while ( i<wSize )
	{
		ch = httpcode[i++];
		if ( (ch=='%')&&(i+1<wSize) )
		{
			httpcode[j++] = 16*getHexValue(httpcode[i]) + getHexValue(httpcode[i+1]);
			i += 2;
		}
		else
		{
			if ( ch=='+' ) httpcode[j++] = ' ';
			else httpcode[j++] = ch;
		}
	}
	httpcode[j] = 0;
}

static void ParseBuffer(CStringList *res, char *line, int bytes, char ch1, char ch2)
{
        int i, cmdHead = 0;
        unsigned char b;
	res->Clear();
        if ( bytes<=0 ) return;
        char Buf1[4096];
        for (i=0;i<bytes;i++)
        {
                b = line[i];
                if ( (b==ch1)||(b==ch2) )
                {
                        if ( cmdHead>0 )
                        {
                                Buf1[cmdHead] = 0;
                                res->Add ( Buf1 );
                                cmdHead = 0;
                        }
                }
                else if ( (cmdHead<4000)&&((cmdHead>0)||(b>32)) )
                {
                        Buf1[cmdHead++] = b;
                }
        }
        if ( cmdHead>0 )
        {
                Buf1[cmdHead] = 0;
                res->Add( Buf1 );
	}
}

void ParseToLine(CStringList *res, char *buf, int bytes)
{
	ParseBuffer(res, buf, bytes, 10, 0);
}

void ParseToItem(CStringList *res, char *line, int bytes, char ch)
{
	ParseBuffer(res, line, bytes, 13, ch);
}

int parseAddress(char *src, char *addr, int &port)
{
	char *p2, *p1 = strchr(src, '/');

	if ( p1!=NULL ) p1 = p1 + 1;
	else p1 = src;

	p2 = strchr(p1, ':');
	if ( p2!=NULL )
	{
		*p2 = 0;
		strncpy(addr, p1, 20);
		port = atoi(p2+1);
		return 1;
	}
	port = 0;
	return 0;
}


/*
 * $Log: comutil.cpp,v $
 * Revision 1.2  2004/01/12 07:57:38  administrator
 * back up 2004-01-12
 * 1. Update NetAT200 driver
 * 2. add ktd348 matrix switcher
 * 3. add hj232 driver
 * 4. add philips keyboard driver
 * 5. add panasonic 850 driver
 *
 * Revision 1.1  2001/05/20 20:25:25  cvsroot
 * *** empty log message ***
 *
 * Revision 1.6  2001/05/07 09:24:41  cvsroot
 * before go to shenzhen
 *
 * Revision 1.5  2001/04/25 17:35:24  cvsroot
 * add control code for stopserver
 *
 * Revision 1.4  2001/01/23 21:53:08  cvsroot
 * add Log in CVS
 *
 * Revision 1.6  2001/01/23 21:51:40  cvsroot
 * add Log in CVS
 *
*/

